Bring in the phyloseq object

#source("Scripts/MakePhyloseqObject.R")
load("IntermediateData/larval_phyloseq.RData")

Required libraries

library(phyloseq)
library(DESeq2)
library(dplyr)
library(ggplot2)
library(vegan)
library(ggrepel)
library(cowplot)
 library(lme4)
library(lmerTest)
 library(broom.mixed)
library(plotly)
library(tidyverse)

Better names for taxa

pull_lowlev <- function(taxaVec){
  taxaVec <- dplyr::select(Kingdom:Genus)
  taxaVec <- na.omit(taxaVec)
  taxaVec[length(taxaVec)]
}

theTaxa <- ps %>% tax_table() %>% as("matrix") %>% data.frame()  #%>% as.data.frame()
theTaxa[] <- lapply(theTaxa, as.character)
theTaxa$ASVNum <- rownames(theTaxa) %>% parse_number
theTaxa$ASVName <- rownames(theTaxa)


myLowist <- theTaxa %>% pivot_longer(Kingdom:Genus) %>% na.omit %>% group_by(ASVName) %>% summarise(Lowist = last(value))

theTaxa <- theTaxa %>% left_join(myLowist, by = "ASVName")
theTaxa <- theTaxa %>% mutate(JName = str_c(Lowist, ASVNum, sep = "_"))
theTaxa <- theTaxa %>% column_to_rownames("ASVName")
head(theTaxa)


tt2 <- tax_table(theTaxa)
Coercing from data.frame class to character matrix 
prior to building taxonomyTable. 
This could introduce artifacts. 
Check your taxonomyTable, or coerce to matrix manually.
rownames(tt2) <- rownames(theTaxa)
colnames(tt2) <- colnames(theTaxa)
ps_retax <- ps
tax_table(ps_retax) <- tt2

Remove blanks

ps_noblank <- subset_samples(ps_retax, Strain != "Blank")
ps_plusone <- transform_sample_counts(ps_noblank, function(x) x + 1)

Convert to relative abundance

psra <- ps %>% transform_sample_counts( function(x) x/sum(x))

Normalize microibal counts to oyster counts

# ps_oyster <- ps %>% subset_taxa(Order == "Ostreoida")
# ps_not_oyster <- ps %>% subset_taxa(Order != "Ostreoida")
# oyster_sums <- otu_table(ps_oyster)@.Data %>% apply(MARGIN = 2, sum)
# not_oyster_counts <- otu_table(ps_not_oyster)@.Data
# 
# over_oyster <- sweep(not_oyster_counts, 2, oyster_sums, "/")
# over_oyster_log10 <- log10(over_oyster)

This is a variance normalizing tranformaiton. Its apparently an alternative to rarifying the data.

deseq_pre <- phyloseq_to_deseq2(ps, design = ~ Project)
converting counts to integer mode
# deseq_counts <- estimateSizeFactors(deseq_pre, type = "poscounts")
# deseq_counts_vst <- varianceStabilizingTransformation(deseq_counts)
# vst_trans_count_tab <- assay(deseq_counts_vst)

# Ella on Slack
#deseq_pre
dds = deseq_pre[rowSums(counts(deseq_pre)) > 5,]
dds_esf <- estimateSizeFactors(dds, type = "poscounts")
dds01 <- DESeq(dds_esf)
using pre-existing size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 851 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
dds_res <- results(dds01)

dds_counts <- counts(dds01, normalized = TRUE)

ps_dds <- ps_retax
otu_table(ps_dds) <- otu_table(dds_counts, taxa_are_rows = TRUE)

Select only species that show up in at least 20% of the samples.

ps_common <- filter_taxa(ps_dds, function(x) sum(x > 2) > (0.2*length(x)), TRUE)
ps_common
phyloseq-class experiment-level object
otu_table()   OTU Table:         [ 463 taxa and 35 samples ]
sample_data() Sample Data:       [ 35 samples by 6 sample variables ]
tax_table()   Taxonomy Table:    [ 463 taxa by 9 taxonomic ranks ]

Devide the abundance of each microbial ASV by the host gene copy number. Now microbial genes are reported as ratios to host, rather than counts. This process adjusts for compositionality.

Normalize microibal counts to oyster counts

ps_oyster <- ps_dds %>% subset_taxa(Order == "Ostreoida")
ps_not_oyster <- ps_common %>% subset_taxa(Order != "Ostreoida") # ok if not common, so just using dds
oyster_sums <- otu_table(ps_oyster)@.Data %>% apply(MARGIN = 2, sum)
not_oyster_counts <- otu_table(ps_not_oyster)@.Data

over_oyster <- sweep(not_oyster_counts, 2, oyster_sums, "/")
# so this suddently contains zeros, making everything fail, but it didn't used to. What gives?
over_oyster_log10 <- log10(over_oyster)
(detection_thresh <- min(na.omit(over_oyster[over_oyster > 0])))
[1] 7.091444e-06
over_oyster_log10 <- log10(over_oyster + detection_thresh)

ps_oo <- ps_not_oyster
otu_table(ps_oo) <- otu_table(over_oyster, taxa_are_rows = TRUE)
ps_oo <- subset_samples(ps_oo, (SampleID %in% c(names(oyster_sums[oyster_sums > 0])))) # remove cases

ps_oo_log <- ps_not_oyster
otu_table(ps_oo_log) <- otu_table(over_oyster_log10, taxa_are_rows = TRUE)

ps_oo_log_ss <- subset_samples(ps_oo_log, !(Project =="Mock"& Strain == "Even" & Run == "NoCrash"))
ps_oo_ss <- subset_samples(ps_oo, !(Project =="Mock"& Strain == "Even" & Run == "NoCrash"))

Make the one figure for the paper

A function I use

converts phyloseq sample data to a data frame

samd_to_df <- function(samd){
  df <- samd %>% sample_data %>% .@.Data %>% lapply(as.character) %>% data.frame
  colnames(df) <- samd@names
  rownames(df) <- samd@row.names
  df
}

Actually run the RDA

Redundancy analysis (RDA) is an ordination approach that allows us to look at how the microbial community as a whole varies across our variables of interest.


ps_oo_log_ss1 <- ps_oo_log_ss %>% subset_samples(((Run =="NoCrash" & Project == "NoCrash") | (Run == "Crash4" & Project == "Crash")) & Treatment %in% c("Fed", "Starve", "Pre"))

test_rda <- rda(t(otu_table(ps_oo_log_ss1)) ~ Project + as.factor(Strain == "Wild") + as.factor(Treatment == "Fed"), data = samd_to_df(sample_data(ps_oo_log_ss1)))
test_rda
Call: rda(formula = t(otu_table(ps_oo_log_ss1)) ~ Project +
as.factor(Strain == "Wild") + as.factor(Treatment == "Fed"), data =
samd_to_df(sample_data(ps_oo_log_ss1)))

               Inertia Proportion Rank
Total         398.6378     1.0000     
Constrained   219.1358     0.5497    3
Unconstrained 179.5020     0.4503   24
Inertia is variance 

Eigenvalues for constrained axes:
  RDA1   RDA2   RDA3 
168.98  41.07   9.09 

Eigenvalues for unconstrained axes:
  PC1   PC2   PC3   PC4   PC5   PC6   PC7   PC8 
45.55 28.02 17.16 13.76  8.03  6.92  5.75  5.37 
(Showing 8 of 24 unconstrained eigenvalues)
test_rda_anova <- anova(test_rda, by = "margin", permutations = how(nperm = 99999))
test_rda_anova
Permutation test for rda under reduced model
Marginal effects of terms
Permutation: free
Number of permutations: 99999

Model: rda(formula = t(otu_table(ps_oo_log_ss1)) ~ Project + as.factor(Strain == "Wild") + as.factor(Treatment == "Fed"), data = samd_to_df(sample_data(ps_oo_log_ss1)))
                              Df Variance       F  Pr(>F)    
Project                        1  154.281 20.6278   1e-05 ***
as.factor(Strain == "Wild")    1   18.224  2.4367 0.05050 .  
as.factor(Treatment == "Fed")  1   37.999  5.0806 0.00249 ** 
Residual                      24  179.502                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
myScores <- scores(test_rda, choices = c(1:4), scaling = "symmetric")

Post procesing of RDA

Sample Data

mySamples <- left_join(
myScores$sites %>% data.frame %>% rownames_to_column("Sample"),
ps_oo_log_ss1 %>% sample_data() %>% samd_to_df %>% rownames_to_column("Sample"),
by = "Sample"
)

Percent variance explained

eigsum <- sum(c(test_rda$CCA$eig, test_rda$CA$eig))
cca_eig <- test_rda$CCA$eig / eigsum
ca_eig <- test_rda$CA$eig / eigsum
all_eig <- c(cca_eig, ca_eig)
all_eig["RDA1"] 
     RDA1 
0.4238992 
rda_eig_pct <- data.frame(all_eig) %>% rownames_to_column("Ax") %>% dplyr::rename(EigPct = "all_eig") %>%
  mutate(Axis2 = ordered(Ax, levels = Ax))
rda_eig_pct

Species

Select which species we will show in the figure, targeting ones that are far from 0, 0.

mySpecies <- left_join(
  myScores$species %>% data.frame %>% rownames_to_column("ASV"),
ps_oo_log_ss1 %>% tax_table() %>% .@.Data %>% as.data.frame %>% rownames_to_column("ASV")
) %>% mutate(RDADist = sqrt(RDA1^2 + RDA2^2 + RDA3 ^2)) %>% 
  arrange(-RDADist) %>%
  head(10) %>%
  mutate(Rank = 1:10)
Joining, by = "ASV"

Calculate Centroids

Centroids tell us about the different treatment types and how they relate to the samples and species.

myCent <- myScores$centroids %>% data.frame %>% rownames_to_column("Treatment") %>%
  tidyr::extract(Treatment, c("Type", "Condition"), "([A-Z][a-z]+)([A-Z].*)",  remove = FALSE) %>%
  mutate(Type = if_else(str_detect(Treatment, "Wild"), "Strain", Type)) %>%
  mutate(Condition = if_else(Type == "Strain" & str_detect(Treatment, "FALSE"), "Tame", Condition)) %>%
  mutate(Condition = if_else(Type == "Strain" & str_detect(Treatment, "TRUE"), "Wild", Condition)) %>%
  mutate(Type = if_else(str_detect(Treatment, "Fed"), "Feeding", Type)) %>%
  mutate(Condition = if_else(Type == "Feeding" & str_detect(Treatment, "FALSE"), "StarvedOrPre", Condition)) %>%
  mutate(Condition = if_else(Type == "Feeding" & str_detect(Treatment, "TRUE"), "Fed", Condition))

myCent2 <- myCent %>% filter((Condition %in% c("Fed", "Wild", "Crash")))

Main Figure

This actually plots the main figure, using ggplot

ccaPlot_1V2_A <- mySamples %>% ggplot(aes(x = RDA1, y = RDA2)) +
  geom_point(size = 3, stroke = 3, aes(shape = Project, color = Strain == "Wild", fill = Treatment), alpha = 1) +
  scale_shape_manual(values = c(21:25)) + scale_color_manual(values = c("gray40", "black")) + scale_fill_manual(values = c(Fed = "Blue", Pre = "DarkGreen", Starve = "Orange", Crash = "Pink", NoCrash = "White", Wild = "White"))+
  geom_point(data = mySpecies, size = 4, shape = "+") + 
  ggrepel::geom_text_repel(data = mySpecies, aes(label = JName) , size = 3) +
  guides(fill = guide_legend(override.aes = list(shape = 21)), color = guide_legend(override.aes = list(shape = 21))) +
  theme(legend.position = "bottom")

ccaLegend <- get_legend(ccaPlot_1V2_A)

ccaPlot_1V2_B <- ccaPlot_1V2_A +
  geom_label(data = myCent2, aes(label = Condition, x = RDA1 * 1.75, y = RDA2 * 2, fill = Condition) , size = 5) +
  geom_segment(data = myCent2, aes(x = 0, y = 0, xend = RDA1 * 2.5, yend = RDA2 * 2.5), arrow = arrow(length = unit(0.1, "in")), alpha = 0.5, size = 1) +
  coord_fixed(sqrt(test_rda$CCA$eig[2]/test_rda$CCA$eig[1])) +
  labs(x = paste0("RDA1", " (", scales::percent(all_eig["RDA1"]), ")"),
       y = paste0("RDA2", " (", scales::percent(all_eig["RDA2"]), ")")
       ) +
  cowplot::theme_cowplot() + theme(legend.position = "none")

#plot_grid(ccaPlot_1V2_B, ccaLegend)
ProtoNewFig <- plot_grid(ccaPlot_1V2_B, ccaLegend, nrow = 2, rel_heights = c(10,1))
ggsave("Figures/ProtoNewFig.svg", ProtoNewFig, width = 8, height = 6)

View Main Figure

The main figure is an .svg file, but here is a draft view for this workbook.

ProtoNewFig

I’m not sure why “NoCrash” and “Wild” showed up in the legend. It didn’t used to do that, but I’m not going to bother to correct this right now.

Seeing which species relate to crash vs non-crash

We don’t show these figures in the paper, but we do refer to them.

Initial data wrangling

ps_oo_log_ss2 <- ps_oo_log_ss1
sample_data(ps_oo_log_ss2) <-  mySamples %>% column_to_rownames("Sample") %>% sample_data()

Reshaping to long takes a little while. (~ 20 seconds)

melt_oo_log_ss2 <- psmelt(ps_oo_log_ss2)
melt2_oo_log_ss2 <- melt_oo_log_ss2 %>%
  mutate(logAbundance = Abundance) %>%
  mutate(Abundance = 10^(Abundance))
melt2_oo_log_ss2 <- melt2_oo_log_ss2 %>% left_join(mySpecies %>% select(RDA1.Spec = RDA1, JName), by = "JName")
melt2_oo_log_ss2 %>% head

Stuff

Run an lme to see if each microbe is related to project, holding out treatment as a mixed effect.

modframe <- melt2_oo_log_ss2 %>% select(Project:Group, logAbundance, Kingdom:Genus, JName ) %>% group_by(JName) %>% nest(data = Project:logAbundance) %>%
  #mutate(mod = map(data, ~tidy(lm(data = ., logAbundance ~ Project)))) %>%
  mutate(lme = map(data, ~tidy(lmer(data = ., logAbundance ~ Project + (1|Treatment) + (1|Strain)))))
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular
boundary (singular) fit: see ?isSingular

Ignore the many warning messages, and don’t ask me what they mean.

And visualize the results

modframe01 <- modframe %>% unnest(lme) %>% filter(term == "ProjectNoCrash") %>% select(Kingdom:JName, estimate, std.error, p.value) %>% mutate(fdr = p.adjust(p.value, method = "BH"))
ggplotly(
ggplot(modframe01, aes(x = estimate, y = log10(p.value),  color = Kingdom, JName = JName)) + geom_point() + 
  scale_color_manual(values = c(Bacteria = "Gray10", Eukaryota = "blue", Archaea = "red")) +
  geom_hline(aes(yintercept = log10(0.01)))
)

Figure 2. Not shown int the paper. Estimate is the size of the coefficint in a linear model. log10 P value tells about significance.

Everything below the line is statistically significant. Mouse over the dots to see which bacteria are which. If plotly is giving you problems, comment out the ggplotly bits and this shows up as a normal plot. But then you can’t mouse over poitns.

How many significant and non significant ASVs are there?

modframe01 %>% ungroup %>% summarise(signif = sum(p.value < 0.01), total = length(p.value)) %>% mutate(frachits = signif/total) 

63 % of the asvs are related to treatment p < 0.01.

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBCcmluZyBpbiB0aGUgcGh5bG9zZXEgb2JqZWN0CgpgYGB7cn0KI3NvdXJjZSgiU2NyaXB0cy9NYWtlUGh5bG9zZXFPYmplY3QuUiIpCmxvYWQoIkludGVybWVkaWF0ZURhdGEvbGFydmFsX3BoeWxvc2VxLlJEYXRhIikKYGBgCgojIFJlcXVpcmVkIGxpYnJhcmllcwoKYGBge3J9CmxpYnJhcnkocGh5bG9zZXEpCmxpYnJhcnkoREVTZXEyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodmVnYW4pCmxpYnJhcnkoZ2dyZXBlbCkKbGlicmFyeShjb3dwbG90KQogbGlicmFyeShsbWU0KQpsaWJyYXJ5KGxtZXJUZXN0KQogbGlicmFyeShicm9vbS5taXhlZCkKbGlicmFyeShwbG90bHkpCmxpYnJhcnkodGlkeXZlcnNlKQoKYGBgCgojIEJldHRlciBuYW1lcyBmb3IgdGF4YQoKCgpgYGB7cn0KcHVsbF9sb3dsZXYgPC0gZnVuY3Rpb24odGF4YVZlYyl7CiAgdGF4YVZlYyA8LSBkcGx5cjo6c2VsZWN0KEtpbmdkb206R2VudXMpCiAgdGF4YVZlYyA8LSBuYS5vbWl0KHRheGFWZWMpCiAgdGF4YVZlY1tsZW5ndGgodGF4YVZlYyldCn0KCnRoZVRheGEgPC0gcHMgJT4lIHRheF90YWJsZSgpICU+JSBhcygibWF0cml4IikgJT4lIGRhdGEuZnJhbWUoKSAgIyU+JSBhcy5kYXRhLmZyYW1lKCkKdGhlVGF4YVtdIDwtIGxhcHBseSh0aGVUYXhhLCBhcy5jaGFyYWN0ZXIpCnRoZVRheGEkQVNWTnVtIDwtIHJvd25hbWVzKHRoZVRheGEpICU+JSBwYXJzZV9udW1iZXIKdGhlVGF4YSRBU1ZOYW1lIDwtIHJvd25hbWVzKHRoZVRheGEpCgoKbXlMb3dpc3QgPC0gdGhlVGF4YSAlPiUgcGl2b3RfbG9uZ2VyKEtpbmdkb206R2VudXMpICU+JSBuYS5vbWl0ICU+JSBncm91cF9ieShBU1ZOYW1lKSAlPiUgc3VtbWFyaXNlKExvd2lzdCA9IGxhc3QodmFsdWUpKQoKdGhlVGF4YSA8LSB0aGVUYXhhICU+JSBsZWZ0X2pvaW4obXlMb3dpc3QsIGJ5ID0gIkFTVk5hbWUiKQp0aGVUYXhhIDwtIHRoZVRheGEgJT4lIG11dGF0ZShKTmFtZSA9IHN0cl9jKExvd2lzdCwgQVNWTnVtLCBzZXAgPSAiXyIpKQp0aGVUYXhhIDwtIHRoZVRheGEgJT4lIGNvbHVtbl90b19yb3duYW1lcygiQVNWTmFtZSIpCmhlYWQodGhlVGF4YSkKCgp0dDIgPC0gdGF4X3RhYmxlKHRoZVRheGEpCnJvd25hbWVzKHR0MikgPC0gcm93bmFtZXModGhlVGF4YSkKY29sbmFtZXModHQyKSA8LSBjb2xuYW1lcyh0aGVUYXhhKQpwc19yZXRheCA8LSBwcwp0YXhfdGFibGUocHNfcmV0YXgpIDwtIHR0MgpgYGAKClJlbW92ZSBibGFua3MKYGBge3J9CnBzX25vYmxhbmsgPC0gc3Vic2V0X3NhbXBsZXMocHNfcmV0YXgsIFN0cmFpbiAhPSAiQmxhbmsiKQpwc19wbHVzb25lIDwtIHRyYW5zZm9ybV9zYW1wbGVfY291bnRzKHBzX25vYmxhbmssIGZ1bmN0aW9uKHgpIHggKyAxKQpgYGAKCkNvbnZlcnQgdG8gcmVsYXRpdmUgYWJ1bmRhbmNlCmBgYHtyfQpwc3JhIDwtIHBzICU+JSB0cmFuc2Zvcm1fc2FtcGxlX2NvdW50cyggZnVuY3Rpb24oeCkgeC9zdW0oeCkpCmBgYAoKTm9ybWFsaXplIG1pY3JvaWJhbCBjb3VudHMgdG8gb3lzdGVyIGNvdW50cwpgYGB7cn0KIyBwc19veXN0ZXIgPC0gcHMgJT4lIHN1YnNldF90YXhhKE9yZGVyID09ICJPc3RyZW9pZGEiKQojIHBzX25vdF9veXN0ZXIgPC0gcHMgJT4lIHN1YnNldF90YXhhKE9yZGVyICE9ICJPc3RyZW9pZGEiKQojIG95c3Rlcl9zdW1zIDwtIG90dV90YWJsZShwc19veXN0ZXIpQC5EYXRhICU+JSBhcHBseShNQVJHSU4gPSAyLCBzdW0pCiMgbm90X295c3Rlcl9jb3VudHMgPC0gb3R1X3RhYmxlKHBzX25vdF9veXN0ZXIpQC5EYXRhCiMgCiMgb3Zlcl9veXN0ZXIgPC0gc3dlZXAobm90X295c3Rlcl9jb3VudHMsIDIsIG95c3Rlcl9zdW1zLCAiLyIpCiMgb3Zlcl9veXN0ZXJfbG9nMTAgPC0gbG9nMTAob3Zlcl9veXN0ZXIpCmBgYAoKVGhpcyBpcyBhIHZhcmlhbmNlIG5vcm1hbGl6aW5nIHRyYW5mb3JtYWl0b24uIEl0cyBhcHBhcmVudGx5IGFuIGFsdGVybmF0aXZlIHRvIHJhcmlmeWluZyB0aGUgZGF0YS4gCmBgYHtyfQpkZXNlcV9wcmUgPC0gcGh5bG9zZXFfdG9fZGVzZXEyKHBzLCBkZXNpZ24gPSB+IFByb2plY3QpCiMgZGVzZXFfY291bnRzIDwtIGVzdGltYXRlU2l6ZUZhY3RvcnMoZGVzZXFfcHJlLCB0eXBlID0gInBvc2NvdW50cyIpCiMgZGVzZXFfY291bnRzX3ZzdCA8LSB2YXJpYW5jZVN0YWJpbGl6aW5nVHJhbnNmb3JtYXRpb24oZGVzZXFfY291bnRzKQojIHZzdF90cmFuc19jb3VudF90YWIgPC0gYXNzYXkoZGVzZXFfY291bnRzX3ZzdCkKCiMgRWxsYSBvbiBTbGFjawojZGVzZXFfcHJlCmRkcyA9IGRlc2VxX3ByZVtyb3dTdW1zKGNvdW50cyhkZXNlcV9wcmUpKSA+IDUsXQpkZHNfZXNmIDwtIGVzdGltYXRlU2l6ZUZhY3RvcnMoZGRzLCB0eXBlID0gInBvc2NvdW50cyIpCmRkczAxIDwtIERFU2VxKGRkc19lc2YpCmRkc19yZXMgPC0gcmVzdWx0cyhkZHMwMSkKCmRkc19jb3VudHMgPC0gY291bnRzKGRkczAxLCBub3JtYWxpemVkID0gVFJVRSkKCnBzX2RkcyA8LSBwc19yZXRheApvdHVfdGFibGUocHNfZGRzKSA8LSBvdHVfdGFibGUoZGRzX2NvdW50cywgdGF4YV9hcmVfcm93cyA9IFRSVUUpCmBgYAoKU2VsZWN0IG9ubHkgc3BlY2llcyB0aGF0IHNob3cgdXAgaW4gYXQgbGVhc3QgMjAlIG9mIHRoZSBzYW1wbGVzLiAKCmBgYHtyfQpwc19jb21tb24gPC0gZmlsdGVyX3RheGEocHNfZGRzLCBmdW5jdGlvbih4KSBzdW0oeCA+IDIpID4gKDAuMipsZW5ndGgoeCkpLCBUUlVFKQpwc19jb21tb24KYGBgCgpEZXZpZGUgdGhlIGFidW5kYW5jZSBvZiBlYWNoIG1pY3JvYmlhbCBBU1YgYnkgdGhlIGhvc3QgZ2VuZSBjb3B5IG51bWJlci4gTm93IG1pY3JvYmlhbCBnZW5lcyBhcmUgcmVwb3J0ZWQgYXMgcmF0aW9zIHRvIGhvc3QsIHJhdGhlciB0aGFuIGNvdW50cy4KVGhpcyBwcm9jZXNzIGFkanVzdHMgZm9yIGNvbXBvc2l0aW9uYWxpdHkuCgpOb3JtYWxpemUgbWljcm9pYmFsIGNvdW50cyB0byBveXN0ZXIgY291bnRzCgpgYGB7cn0KcHNfb3lzdGVyIDwtIHBzX2RkcyAlPiUgc3Vic2V0X3RheGEoT3JkZXIgPT0gIk9zdHJlb2lkYSIpCnBzX25vdF9veXN0ZXIgPC0gcHNfY29tbW9uICU+JSBzdWJzZXRfdGF4YShPcmRlciAhPSAiT3N0cmVvaWRhIikgIyBvayBpZiBub3QgY29tbW9uLCBzbyBqdXN0IHVzaW5nIGRkcwpveXN0ZXJfc3VtcyA8LSBvdHVfdGFibGUocHNfb3lzdGVyKUAuRGF0YSAlPiUgYXBwbHkoTUFSR0lOID0gMiwgc3VtKQpub3Rfb3lzdGVyX2NvdW50cyA8LSBvdHVfdGFibGUocHNfbm90X295c3RlcilALkRhdGEKCm92ZXJfb3lzdGVyIDwtIHN3ZWVwKG5vdF9veXN0ZXJfY291bnRzLCAyLCBveXN0ZXJfc3VtcywgIi8iKQojIHNvIHRoaXMgc3VkZGVudGx5IGNvbnRhaW5zIHplcm9zLCBtYWtpbmcgZXZlcnl0aGluZyBmYWlsLCBidXQgaXQgZGlkbid0IHVzZWQgdG8uIFdoYXQgZ2l2ZXM/Cm92ZXJfb3lzdGVyX2xvZzEwIDwtIGxvZzEwKG92ZXJfb3lzdGVyKQooZGV0ZWN0aW9uX3RocmVzaCA8LSBtaW4obmEub21pdChvdmVyX295c3RlcltvdmVyX295c3RlciA+IDBdKSkpCm92ZXJfb3lzdGVyX2xvZzEwIDwtIGxvZzEwKG92ZXJfb3lzdGVyICsgZGV0ZWN0aW9uX3RocmVzaCkKCnBzX29vIDwtIHBzX25vdF9veXN0ZXIKb3R1X3RhYmxlKHBzX29vKSA8LSBvdHVfdGFibGUob3Zlcl9veXN0ZXIsIHRheGFfYXJlX3Jvd3MgPSBUUlVFKQpwc19vbyA8LSBzdWJzZXRfc2FtcGxlcyhwc19vbywgKFNhbXBsZUlEICVpbiUgYyhuYW1lcyhveXN0ZXJfc3Vtc1tveXN0ZXJfc3VtcyA+IDBdKSkpKSAjIHJlbW92ZSBjYXNlcwoKcHNfb29fbG9nIDwtIHBzX25vdF9veXN0ZXIKb3R1X3RhYmxlKHBzX29vX2xvZykgPC0gb3R1X3RhYmxlKG92ZXJfb3lzdGVyX2xvZzEwLCB0YXhhX2FyZV9yb3dzID0gVFJVRSkKCnBzX29vX2xvZ19zcyA8LSBzdWJzZXRfc2FtcGxlcyhwc19vb19sb2csICEoUHJvamVjdCA9PSJNb2NrIiYgU3RyYWluID09ICJFdmVuIiAmIFJ1biA9PSAiTm9DcmFzaCIpKQpwc19vb19zcyA8LSBzdWJzZXRfc2FtcGxlcyhwc19vbywgIShQcm9qZWN0ID09Ik1vY2siJiBTdHJhaW4gPT0gIkV2ZW4iICYgUnVuID09ICJOb0NyYXNoIikpCmBgYAoKIyBNYWtlIHRoZSBvbmUgZmlndXJlIGZvciB0aGUgcGFwZXIKCiMjIEEgZnVuY3Rpb24gSSB1c2UKY29udmVydHMgcGh5bG9zZXEgc2FtcGxlIGRhdGEgdG8gYSBkYXRhIGZyYW1lCmBgYHtyfQpzYW1kX3RvX2RmIDwtIGZ1bmN0aW9uKHNhbWQpewogIGRmIDwtIHNhbWQgJT4lIHNhbXBsZV9kYXRhICU+JSAuQC5EYXRhICU+JSBsYXBwbHkoYXMuY2hhcmFjdGVyKSAlPiUgZGF0YS5mcmFtZQogIGNvbG5hbWVzKGRmKSA8LSBzYW1kQG5hbWVzCiAgcm93bmFtZXMoZGYpIDwtIHNhbWRAcm93Lm5hbWVzCiAgZGYKfQpgYGAKCiMjIEFjdHVhbGx5IHJ1biB0aGUgUkRBClJlZHVuZGFuY3kgYW5hbHlzaXMgKFJEQSkgaXMgYW4gb3JkaW5hdGlvbiBhcHByb2FjaCB0aGF0IGFsbG93cyB1cyB0byBsb29rIGF0IGhvdyB0aGUgbWljcm9iaWFsIGNvbW11bml0eSBhcyBhIHdob2xlIHZhcmllcyBhY3Jvc3Mgb3VyIHZhcmlhYmxlcyBvZiBpbnRlcmVzdC4KYGBge3J9Cgpwc19vb19sb2dfc3MxIDwtIHBzX29vX2xvZ19zcyAlPiUgc3Vic2V0X3NhbXBsZXMoKChSdW4gPT0iTm9DcmFzaCIgJiBQcm9qZWN0ID09ICJOb0NyYXNoIikgfCAoUnVuID09ICJDcmFzaDQiICYgUHJvamVjdCA9PSAiQ3Jhc2giKSkgJiBUcmVhdG1lbnQgJWluJSBjKCJGZWQiLCAiU3RhcnZlIiwgIlByZSIpKQoKdGVzdF9yZGEgPC0gcmRhKHQob3R1X3RhYmxlKHBzX29vX2xvZ19zczEpKSB+IFByb2plY3QgKyBhcy5mYWN0b3IoU3RyYWluID09ICJXaWxkIikgKyBhcy5mYWN0b3IoVHJlYXRtZW50ID09ICJGZWQiKSwgZGF0YSA9IHNhbWRfdG9fZGYoc2FtcGxlX2RhdGEocHNfb29fbG9nX3NzMSkpKQp0ZXN0X3JkYQp0ZXN0X3JkYV9hbm92YSA8LSBhbm92YSh0ZXN0X3JkYSwgYnkgPSAibWFyZ2luIiwgcGVybXV0YXRpb25zID0gaG93KG5wZXJtID0gOTk5OTkpKQp0ZXN0X3JkYV9hbm92YQpteVNjb3JlcyA8LSBzY29yZXModGVzdF9yZGEsIGNob2ljZXMgPSBjKDE6NCksIHNjYWxpbmcgPSAic3ltbWV0cmljIikKYGBgCgojIyBQb3N0IHByb2Nlc2luZyBvZiBSREEKCiMjIyBTYW1wbGUgRGF0YQpgYGB7cn0KbXlTYW1wbGVzIDwtIGxlZnRfam9pbigKbXlTY29yZXMkc2l0ZXMgJT4lIGRhdGEuZnJhbWUgJT4lIHJvd25hbWVzX3RvX2NvbHVtbigiU2FtcGxlIiksCnBzX29vX2xvZ19zczEgJT4lIHNhbXBsZV9kYXRhKCkgJT4lIHNhbWRfdG9fZGYgJT4lIHJvd25hbWVzX3RvX2NvbHVtbigiU2FtcGxlIiksCmJ5ID0gIlNhbXBsZSIKKQpgYGAKCiMjIyBQZXJjZW50IHZhcmlhbmNlIGV4cGxhaW5lZApgYGB7cn0KZWlnc3VtIDwtIHN1bShjKHRlc3RfcmRhJENDQSRlaWcsIHRlc3RfcmRhJENBJGVpZykpCmNjYV9laWcgPC0gdGVzdF9yZGEkQ0NBJGVpZyAvIGVpZ3N1bQpjYV9laWcgPC0gdGVzdF9yZGEkQ0EkZWlnIC8gZWlnc3VtCmFsbF9laWcgPC0gYyhjY2FfZWlnLCBjYV9laWcpCmFsbF9laWdbIlJEQTEiXSAKYGBgCgpgYGB7cn0KcmRhX2VpZ19wY3QgPC0gZGF0YS5mcmFtZShhbGxfZWlnKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJBeCIpICU+JSBkcGx5cjo6cmVuYW1lKEVpZ1BjdCA9ICJhbGxfZWlnIikgJT4lCiAgbXV0YXRlKEF4aXMyID0gb3JkZXJlZChBeCwgbGV2ZWxzID0gQXgpKQpyZGFfZWlnX3BjdApgYGAKCiMjIyBTcGVjaWVzClNlbGVjdCB3aGljaCBzcGVjaWVzIHdlIHdpbGwgc2hvdyBpbiB0aGUgZmlndXJlLCB0YXJnZXRpbmcgb25lcyB0aGF0IGFyZSBmYXIgZnJvbSAwLCAwLgpgYGB7cn0KbXlTcGVjaWVzIDwtIGxlZnRfam9pbigKICBteVNjb3JlcyRzcGVjaWVzICU+JSBkYXRhLmZyYW1lICU+JSByb3duYW1lc190b19jb2x1bW4oIkFTViIpLApwc19vb19sb2dfc3MxICU+JSB0YXhfdGFibGUoKSAlPiUgLkAuRGF0YSAlPiUgYXMuZGF0YS5mcmFtZSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJBU1YiKQopICU+JSBtdXRhdGUoUkRBRGlzdCA9IHNxcnQoUkRBMV4yICsgUkRBMl4yICsgUkRBMyBeMikpICU+JSAKICBhcnJhbmdlKC1SREFEaXN0KSAlPiUKICBoZWFkKDEwKSAlPiUKICBtdXRhdGUoUmFuayA9IDE6MTApCmBgYAoKIyMgQ2FsY3VsYXRlIENlbnRyb2lkcwpDZW50cm9pZHMgdGVsbCB1cyBhYm91dCB0aGUgZGlmZmVyZW50IHRyZWF0bWVudCB0eXBlcyBhbmQgaG93IHRoZXkgcmVsYXRlIHRvIHRoZSBzYW1wbGVzIGFuZCBzcGVjaWVzLgpgYGB7cn0KbXlDZW50IDwtIG15U2NvcmVzJGNlbnRyb2lkcyAlPiUgZGF0YS5mcmFtZSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJUcmVhdG1lbnQiKSAlPiUKICB0aWR5cjo6ZXh0cmFjdChUcmVhdG1lbnQsIGMoIlR5cGUiLCAiQ29uZGl0aW9uIiksICIoW0EtWl1bYS16XSspKFtBLVpdLiopIiwgIHJlbW92ZSA9IEZBTFNFKSAlPiUKICBtdXRhdGUoVHlwZSA9IGlmX2Vsc2Uoc3RyX2RldGVjdChUcmVhdG1lbnQsICJXaWxkIiksICJTdHJhaW4iLCBUeXBlKSkgJT4lCiAgbXV0YXRlKENvbmRpdGlvbiA9IGlmX2Vsc2UoVHlwZSA9PSAiU3RyYWluIiAmIHN0cl9kZXRlY3QoVHJlYXRtZW50LCAiRkFMU0UiKSwgIlRhbWUiLCBDb25kaXRpb24pKSAlPiUKICBtdXRhdGUoQ29uZGl0aW9uID0gaWZfZWxzZShUeXBlID09ICJTdHJhaW4iICYgc3RyX2RldGVjdChUcmVhdG1lbnQsICJUUlVFIiksICJXaWxkIiwgQ29uZGl0aW9uKSkgJT4lCiAgbXV0YXRlKFR5cGUgPSBpZl9lbHNlKHN0cl9kZXRlY3QoVHJlYXRtZW50LCAiRmVkIiksICJGZWVkaW5nIiwgVHlwZSkpICU+JQogIG11dGF0ZShDb25kaXRpb24gPSBpZl9lbHNlKFR5cGUgPT0gIkZlZWRpbmciICYgc3RyX2RldGVjdChUcmVhdG1lbnQsICJGQUxTRSIpLCAiU3RhcnZlZE9yUHJlIiwgQ29uZGl0aW9uKSkgJT4lCiAgbXV0YXRlKENvbmRpdGlvbiA9IGlmX2Vsc2UoVHlwZSA9PSAiRmVlZGluZyIgJiBzdHJfZGV0ZWN0KFRyZWF0bWVudCwgIlRSVUUiKSwgIkZlZCIsIENvbmRpdGlvbikpCgpteUNlbnQyIDwtIG15Q2VudCAlPiUgZmlsdGVyKChDb25kaXRpb24gJWluJSBjKCJGZWQiLCAiV2lsZCIsICJDcmFzaCIpKSkKYGBgCgojIyMgTWFpbiBGaWd1cmUKVGhpcyBhY3R1YWxseSBwbG90cyB0aGUgbWFpbiBmaWd1cmUsIHVzaW5nIGdncGxvdApgYGB7cn0KY2NhUGxvdF8xVjJfQSA8LSBteVNhbXBsZXMgJT4lIGdncGxvdChhZXMoeCA9IFJEQTEsIHkgPSBSREEyKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIHN0cm9rZSA9IDMsIGFlcyhzaGFwZSA9IFByb2plY3QsIGNvbG9yID0gU3RyYWluID09ICJXaWxkIiwgZmlsbCA9IFRyZWF0bWVudCksIGFscGhhID0gMSkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIxOjI1KSkgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiZ3JheTQwIiwgImJsYWNrIikpICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYyhGZWQgPSAiQmx1ZSIsIFByZSA9ICJEYXJrR3JlZW4iLCBTdGFydmUgPSAiT3JhbmdlIiwgQ3Jhc2ggPSAiUGluayIsIE5vQ3Jhc2ggPSAiV2hpdGUiLCBXaWxkID0gIldoaXRlIikpKwogIGdlb21fcG9pbnQoZGF0YSA9IG15U3BlY2llcywgc2l6ZSA9IDQsIHNoYXBlID0gIisiKSArIAogIGdncmVwZWw6Omdlb21fdGV4dF9yZXBlbChkYXRhID0gbXlTcGVjaWVzLCBhZXMobGFiZWwgPSBKTmFtZSkgLCBzaXplID0gMykgKwogIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2hhcGUgPSAyMSkpLCBjb2xvciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNoYXBlID0gMjEpKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQoKY2NhTGVnZW5kIDwtIGdldF9sZWdlbmQoY2NhUGxvdF8xVjJfQSkKCmNjYVBsb3RfMVYyX0IgPC0gY2NhUGxvdF8xVjJfQSArCiAgZ2VvbV9sYWJlbChkYXRhID0gbXlDZW50MiwgYWVzKGxhYmVsID0gQ29uZGl0aW9uLCB4ID0gUkRBMSAqIDEuNzUsIHkgPSBSREEyICogMiwgZmlsbCA9IENvbmRpdGlvbikgLCBzaXplID0gNSkgKwogIGdlb21fc2VnbWVudChkYXRhID0gbXlDZW50MiwgYWVzKHggPSAwLCB5ID0gMCwgeGVuZCA9IFJEQTEgKiAyLjUsIHllbmQgPSBSREEyICogMi41KSwgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDAuMSwgImluIikpLCBhbHBoYSA9IDAuNSwgc2l6ZSA9IDEpICsKICBjb29yZF9maXhlZChzcXJ0KHRlc3RfcmRhJENDQSRlaWdbMl0vdGVzdF9yZGEkQ0NBJGVpZ1sxXSkpICsKICBsYWJzKHggPSBwYXN0ZTAoIlJEQTEiLCAiICgiLCBzY2FsZXM6OnBlcmNlbnQoYWxsX2VpZ1siUkRBMSJdKSwgIikiKSwKICAgICAgIHkgPSBwYXN0ZTAoIlJEQTIiLCAiICgiLCBzY2FsZXM6OnBlcmNlbnQoYWxsX2VpZ1siUkRBMiJdKSwgIikiKQogICAgICAgKSArCiAgY293cGxvdDo6dGhlbWVfY293cGxvdCgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKI3Bsb3RfZ3JpZChjY2FQbG90XzFWMl9CLCBjY2FMZWdlbmQpClByb3RvTmV3RmlnIDwtIHBsb3RfZ3JpZChjY2FQbG90XzFWMl9CLCBjY2FMZWdlbmQsIG5yb3cgPSAyLCByZWxfaGVpZ2h0cyA9IGMoMTAsMSkpCmdnc2F2ZSgiRmlndXJlcy9Qcm90b05ld0ZpZy5zdmciLCBQcm90b05ld0ZpZywgd2lkdGggPSA4LCBoZWlnaHQgPSA2KQpgYGAKCiMjIyBWaWV3IE1haW4gRmlndXJlCgpUaGUgbWFpbiBmaWd1cmUgaXMgYW4gLnN2ZyBmaWxlLCBidXQgaGVyZSBpcyBhIGRyYWZ0IHZpZXcgZm9yIHRoaXMgd29ya2Jvb2suCmBgYHtyfQpQcm90b05ld0ZpZwpgYGAKCkknbSBub3Qgc3VyZSB3aHkgIk5vQ3Jhc2giIGFuZCAiV2lsZCIgc2hvd2VkIHVwIGluIHRoZSBsZWdlbmQuIEl0IGRpZG4ndCB1c2VkIHRvIGRvIHRoYXQsIGJ1dCBJJ20gbm90IGdvaW5nIHRvIGJvdGhlciB0byBjb3JyZWN0IHRoaXMgcmlnaHQgbm93LgoKIyBTZWVpbmcgd2hpY2ggc3BlY2llcyByZWxhdGUgdG8gY3Jhc2ggdnMgbm9uLWNyYXNoCldlIGRvbid0IHNob3cgdGhlc2UgZmlndXJlcyBpbiB0aGUgcGFwZXIsIGJ1dCB3ZSBkbyByZWZlciB0byB0aGVtLgoKIyMgSW5pdGlhbCBkYXRhIHdyYW5nbGluZwoKYGBge3J9CnBzX29vX2xvZ19zczIgPC0gcHNfb29fbG9nX3NzMQpzYW1wbGVfZGF0YShwc19vb19sb2dfc3MyKSA8LSAgbXlTYW1wbGVzICU+JSBjb2x1bW5fdG9fcm93bmFtZXMoIlNhbXBsZSIpICU+JSBzYW1wbGVfZGF0YSgpCmBgYAoKUmVzaGFwaW5nIHRvIGxvbmcgdGFrZXMgYSBsaXR0bGUgd2hpbGUuICh+IDIwIHNlY29uZHMpCmBgYHtyfQptZWx0X29vX2xvZ19zczIgPC0gcHNtZWx0KHBzX29vX2xvZ19zczIpCmBgYAoKYGBge3J9Cm1lbHQyX29vX2xvZ19zczIgPC0gbWVsdF9vb19sb2dfc3MyICU+JQogIG11dGF0ZShsb2dBYnVuZGFuY2UgPSBBYnVuZGFuY2UpICU+JQogIG11dGF0ZShBYnVuZGFuY2UgPSAxMF4oQWJ1bmRhbmNlKSkKbWVsdDJfb29fbG9nX3NzMiA8LSBtZWx0Ml9vb19sb2dfc3MyICU+JSBsZWZ0X2pvaW4obXlTcGVjaWVzICU+JSBzZWxlY3QoUkRBMS5TcGVjID0gUkRBMSwgSk5hbWUpLCBieSA9ICJKTmFtZSIpCm1lbHQyX29vX2xvZ19zczIgJT4lIGhlYWQKYGBgCgojIyBTdHVmZgoKUnVuIGFuIGxtZSB0byBzZWUgaWYgZWFjaCBtaWNyb2JlIGlzIHJlbGF0ZWQgdG8gcHJvamVjdCwgaG9sZGluZyBvdXQgdHJlYXRtZW50IGFzIGEgbWl4ZWQgZWZmZWN0LgoKYGBge3J9Cm1vZGZyYW1lIDwtIG1lbHQyX29vX2xvZ19zczIgJT4lIHNlbGVjdChQcm9qZWN0Okdyb3VwLCBsb2dBYnVuZGFuY2UsIEtpbmdkb206R2VudXMsIEpOYW1lICkgJT4lIGdyb3VwX2J5KEpOYW1lKSAlPiUgbmVzdChkYXRhID0gUHJvamVjdDpsb2dBYnVuZGFuY2UpICU+JQogICNtdXRhdGUobW9kID0gbWFwKGRhdGEsIH50aWR5KGxtKGRhdGEgPSAuLCBsb2dBYnVuZGFuY2UgfiBQcm9qZWN0KSkpKSAlPiUKICBtdXRhdGUobG1lID0gbWFwKGRhdGEsIH50aWR5KGxtZXIoZGF0YSA9IC4sIGxvZ0FidW5kYW5jZSB+IFByb2plY3QgKyAoMXxUcmVhdG1lbnQpICsgKDF8U3RyYWluKSkpKSkKYGBgCklnbm9yZSB0aGUgbWFueSB3YXJuaW5nIG1lc3NhZ2VzLCBhbmQgZG9uJ3QgYXNrIG1lIHdoYXQgdGhleSBtZWFuLgoKQW5kIHZpc3VhbGl6ZSB0aGUgcmVzdWx0cwpgYGB7cn0KbW9kZnJhbWUwMSA8LSBtb2RmcmFtZSAlPiUgdW5uZXN0KGxtZSkgJT4lIGZpbHRlcih0ZXJtID09ICJQcm9qZWN0Tm9DcmFzaCIpICU+JSBzZWxlY3QoS2luZ2RvbTpKTmFtZSwgZXN0aW1hdGUsIHN0ZC5lcnJvciwgcC52YWx1ZSkgJT4lIG11dGF0ZShmZHIgPSBwLmFkanVzdChwLnZhbHVlLCBtZXRob2QgPSAiQkgiKSkKYGBgCgpgYGB7cn0KZ2dwbG90bHkoCmdncGxvdChtb2RmcmFtZTAxLCBhZXMoeCA9IGVzdGltYXRlLCB5ID0gbG9nMTAocC52YWx1ZSksICBjb2xvciA9IEtpbmdkb20sIEpOYW1lID0gSk5hbWUpKSArIGdlb21fcG9pbnQoKSArIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKEJhY3RlcmlhID0gIkdyYXkxMCIsIEV1a2FyeW90YSA9ICJibHVlIiwgQXJjaGFlYSA9ICJyZWQiKSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBsb2cxMCgwLjAxKSkpCikKYGBgCgpGaWd1cmUgMi4gTm90IHNob3duIGludCB0aGUgcGFwZXIuIEVzdGltYXRlIGlzIHRoZSBzaXplIG9mIHRoZSBjb2VmZmljaW50IGluIGEgbGluZWFyIG1vZGVsLiBsb2cxMCBQIHZhbHVlIHRlbGxzIGFib3V0IHNpZ25pZmljYW5jZS4gCgpFdmVyeXRoaW5nIGJlbG93IHRoZSBsaW5lIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuIE1vdXNlIG92ZXIgdGhlIGRvdHMgdG8gc2VlIHdoaWNoIGJhY3RlcmlhIGFyZSB3aGljaC4gSWYgcGxvdGx5IGlzIGdpdmluZyB5b3UgcHJvYmxlbXMsIGNvbW1lbnQgb3V0IHRoZSBgZ2dwbG90bHlgIGJpdHMgYW5kIHRoaXMgc2hvd3MgdXAgYXMgYSBub3JtYWwgcGxvdC4gQnV0IHRoZW4geW91IGNhbid0IG1vdXNlIG92ZXIgcG9pdG5zLgoKSG93IG1hbnkgc2lnbmlmaWNhbnQgYW5kIG5vbiBzaWduaWZpY2FudCBBU1ZzIGFyZSB0aGVyZT8KCmBgYHtyfQptb2RmcmFtZTAxICU+JSB1bmdyb3VwICU+JSBzdW1tYXJpc2Uoc2lnbmlmID0gc3VtKHAudmFsdWUgPCAwLjAxKSwgdG90YWwgPSBsZW5ndGgocC52YWx1ZSkpICU+JSBtdXRhdGUoZnJhY2hpdHMgPSBzaWduaWYvdG90YWwpIApgYGAKNjMgJSBvZiB0aGUgYXN2cyBhcmUgcmVsYXRlZCB0byB0cmVhdG1lbnQgcCA8IDAuMDEu